/*
 * @Author: dingyuwen ding_yuwen@163.com
 * @Date: 2023-05-10 09:21:00
 * @LastEditTime: 2023-11-08 11:41:56
 * @LastEditors: DingYuwen 43669762+DingYuwen@users.noreply.github.com
 * @Description:
 */

import {
  Flex,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  Text,
  useDisclosure,
  useToast,
} from '@chakra-ui/react';
import { shuffle } from 'lodash-es';
import { useEffect, useCallback } from 'react';
import { RootState } from 'store/store';
import { useAppDispatch, useAppSelector } from 'store/storeHooks';
import { userInvoked } from 'store/actions';
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
import { setPositivePrompt } from 'features/parameters/store/generationSlice';
import {
  clearSelectedOption,
  Question,
  setPromptMap,
  setQuestionList,
} from 'features/question/store/questionSlice';
import questionListData from 'features/question/data/questionList';
import QuestionList from 'features/question/components/QuestionList';
import InvokeButton from './components/ProcessButton';
import AppBackground from './components/AppBackground';
import SocketStatus from 'common/components/SocketStatus';
import ImageToDisplay from '../features/gallery/components/ImageToDisplay';
import ParamMainModel from './components/ParamMainModel';

export default function Meidu() {
  const dispatch = useAppDispatch();
  const toast = useToast();
  const questionNumber = Number(import.meta.env.VITE_QUESTION_NUMBER) || 2;

  const { selectedOption, promptMap } = useAppSelector(
    (store: RootState) => store.question
  );

  const { isOpen, onOpen, onClose } = useDisclosure();

  const questionInit = useCallback(() => {
    const question: Question[] = JSON.parse(JSON.stringify(questionListData));
    question.forEach((q) => {
      const allOption = q.option;
      const option = shuffle(allOption.map((_, i) => i))
        .slice(0, 4)
        .map((i: number) => allOption[i]);
      q.option = option;
    });
    const _promptMap = question.reduce((p: { [k: string]: string }, t) => {
      t.option.forEach((o) => {
        p[`${t.id}-${o.id}`] = o.prompt;
      });
      return p;
    }, {});
    dispatch(setPromptMap(_promptMap));
    dispatch(setQuestionList(question));
  }, [dispatch]);

  const handleGenerateImage = () => {
    if (Object.keys(selectedOption).length !== questionNumber) {
      return toast({
        duration: 3000,
        render: () => (
          <Flex
            flexDir="column"
            color="brand.800"
            p={3}
            bg="brand.100"
            align="center"
          >
            <Text>Please answer the question first.</Text>
            <Text>请先回答问题</Text>
          </Flex>
        ),
      });
    }
    const prompts = Object.keys(selectedOption)
      .map((qId) => promptMap[`${qId}-${selectedOption[qId]}`])
      .join(',');

    dispatch(setPositivePrompt(prompts));
    Promise.resolve().then(() => {
      dispatch(clampSymmetrySteps());
      dispatch(userInvoked('txt2img'));
      onOpen();
    });
  };

  useEffect(() => {
    questionInit();
  }, [questionInit]);

  return (
    <AppBackground withBanner>
      <SocketStatus />
      <Flex flexDir="column" grow="1">
        <Flex
          px={{ base: '2', sm: '3', md: '4', lg: '6', xl: '10', '2xl': '14' }}
          flexDirection="column"
          justify="center"
          align="center"
          grow="1"
        >
          <QuestionList />
        </Flex>
        <Flex
          py={{
            base: 2,
            lg: 4,
            xl: 6,
            '2xl': 8,
            '1080p': 10,
            '2k': 14,
            '4k': 20,
          }}
          justify="center"
        >
          <InvokeButton handleInvoke={handleGenerateImage} />
        </Flex>
      </Flex>
      <Modal
        onClose={() => {
          dispatch(clearSelectedOption());
          // 刷新题目
          questionInit();
          // todo: 如果会话中关闭，需要终止绘画，重置状态
          onClose();
        }}
        isOpen={isOpen}
        size="full"
      >
        <ModalContent bgColor="white" h="100vh" outline="none">
          <ModalCloseButton color="brand.700" />
          <ModalBody p="0">
            <AppBackground withBanner>
              <ImageToDisplay />
            </AppBackground>
          </ModalBody>
        </ModalContent>
      </Modal>
      <ParamMainModel />
    </AppBackground>
  );
}
